//
//  JPApiProxy.m
//  JPWords
//
//  Created by 梁淑婷 on 2024/4/20.
//

#import "JPApiProxy.h"
#import <AFNetworking/AFHTTPSessionManager.h>
#import "JPURLResponse.h"
#import "JPLogger.h"
#import "JPServiceFactory.h"
#import "NSURLRequest+JPNetworkingMethods.h"
#import "NSString+JPNetworkingMethods.h"
#import "NSObject+JPNetworkingMethods.h"

static NSString * const kAXApiProxyDispatchItemKeyCallbackSuccess = @"kAXApiProxyDispatchItemCallbackSuccess";
static NSString * const kAXApiProxyDispatchItemKeyCallbackFail = @"kAXApiProxyDispatchItemCallbackFail";

NSString * const kJPApiProxyValidateResultKeyResponseJSONObject = @"kJPApiProxyValidateResultKeyResponseJSONObject";
NSString * const kJPApiProxyValidateResultKeyResponseJSONString = @"kJPApiProxyValidateResultKeyResponseJSONString";
NSString * const kJPApiProxyValidateResultKeyResponseData = @"kJPApiProxyValidateResultKeyResponseData";

@interface JPApiProxy ()

@property (nonatomic, strong) NSMutableDictionary *dispatchTable;
@property (nonatomic, strong) NSNumber *recordedRequestId;
@property (nonatomic, strong) AFHTTPSessionManager *sessionManager;

@end

@implementation JPApiProxy

JP_SINGLETON_IMP(JPApiProxy);

#pragma mark - getters and setters
- (NSMutableDictionary *)dispatchTable
{
    if (_dispatchTable == nil) {
        _dispatchTable = [[NSMutableDictionary alloc] init];
    }
    return _dispatchTable;
}

- (AFHTTPSessionManager *)sessionManager
{
    if (_sessionManager == nil) {
        AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
        manager.requestSerializer = [AFJSONRequestSerializer serializer];
        manager.responseSerializer = ^{
            AFJSONResponseSerializer *response = [AFJSONResponseSerializer serializer];
            response.removesKeysWithNullValues = YES;
            return response;
        }();
        
        manager.securityPolicy = ^{
            AFSecurityPolicy *securityPolicy = [AFSecurityPolicy defaultPolicy];
            // 客户端是否信任非法证书
            securityPolicy.allowInvalidCertificates = YES;
            // 是否在证书域字段中验证域名
            securityPolicy.validatesDomainName = NO;
            return securityPolicy;
        }();
        
        _sessionManager = manager;
    }
    return _sessionManager;
}


#pragma mark - public methods
- (void)cancelRequestWithRequestID:(NSNumber *)requestID
{
    NSURLSessionDataTask *requestOperation = self.dispatchTable[requestID];
    [requestOperation cancel];
    [self.dispatchTable removeObjectForKey:requestID];
}

- (void)cancelRequestWithRequestIDList:(NSArray *)requestIDList
{
    for (NSNumber *requestId in requestIDList) {
        [self cancelRequestWithRequestID:requestId];
    }
}

/** 这个函数存在的意义在于，如果将来要把AFNetworking换掉，只要修改这个函数的实现即可。 */
- (NSNumber *)callApiWithRequest:(NSURLRequest *)request success:(JPCallback)success fail:(JPCallback)fail
{
    // 跑到这里的block的时候，就已经是主线程了。
    __block NSURLSessionDataTask *dataTask = nil;
    void (^completionHandler)(NSURLResponse *response, id _Nullable responseObject,  NSError * _Nullable error) = ^(NSURLResponse * _Nonnull response, NSData * _Nullable responseData, NSError * _Nullable error) {
        NSNumber *requestID = @([dataTask taskIdentifier]);
        [self.dispatchTable removeObjectForKey:requestID];
        
        NSDictionary *result = [request.service resultWithResponseData:responseData response:response request:request error:&error];
        NSData *jsonData = result[kJPApiProxyValidateResultKeyResponseData];
        NSString *jsonString = result[kJPApiProxyValidateResultKeyResponseJSONString];
        NSDictionary *jsonObject = result[kJPApiProxyValidateResultKeyResponseJSONObject];

        // 输出返回数据
        JPURLResponse *JPResponse = ^{
            return [[JPURLResponse alloc] initWithResponseString:jsonString
                                                        requestId:requestID
                                                          request:request
                                                  responseContent:jsonObject
                                                            error:error];
        }();
        
        JPResponse.logString = ^{
            return [JPLogger logDebugInfoWithResponse:(NSHTTPURLResponse *)response
                                       rawResponseData:jsonData
                                        responseString:jsonString
                                               request:request
                                                 error:error];
        }();
        
        if (error) {
            fail?fail(JPResponse):nil;
        } else {
            success?success(JPResponse):nil;
        }
    };
    dataTask = [self.sessionManager dataTaskWithRequest:request
                                         uploadProgress:nil
                                       downloadProgress:nil
                                      completionHandler:completionHandler];
    NSNumber *requestId = @([dataTask taskIdentifier]);
    
    self.dispatchTable[requestId] = dataTask;
    [dataTask resume];
    
    return requestId;
}


@end
